
import Foundation


extension Data {
    
    /// 分块打印（每行16字节，带地址和ASCII解码）
    func hexDump() {
        let chunkSize = 16
        let length = self.count
        
        for offset in stride(from: 0, to: length, by: chunkSize) {
            // 打印地址
            print(String(format: "%08X  ", offset), terminator: "")
            
            // 打印十六进制内容
            let chunk = self[offset..<Swift.min(offset + chunkSize, length)]
            var hexLine = ""
            var asciiLine = ""
            
            for (index, byte) in chunk.enumerated() {
                hexLine += String(format: "%02x ", byte)
                asciiLine += (byte >= 32 && byte <= 126) ? String(UnicodeScalar(byte)) : "."
                
                if index == 7 { hexLine += " " } // 每8字节加空格分隔
            }
            
            // 对齐格式
            hexLine = hexLine.padding(toLength: 49, withPad: " ", startingAt: 0)
            printf("\(hexLine)  |\(asciiLine)|")
        }
    }

    func hexSpacedString() -> String {
        self.enumerated().map { index, byte in
            String(format: "%02hhx\(index % 4 == 3 ? "  " : " ")", byte)
        }.joined().trimmingCharacters(in: .whitespaces)
    }
    
    func hexEncodedString() -> String {
        return map { String(format: "%02hhx", $0) }.joined()
    }
    
    var hexString: String {
        map { String(format: "%02x", $0) }.joined()
    }
    
    init?(hexString: String) {
        let len = hexString.count / 2
        var data = Data(capacity: len)
        var hex = hexString
        while !hex.isEmpty {
            let start = hex.startIndex
            let end = hex.index(start, offsetBy: 2)
            let byteString = hex[start..<end]
            if let byte = UInt8(byteString, radix: 16) {
                data.append(byte)
            } else {
                return nil
            }
            hex = String(hex[end...])
        }
        self = data
    }
    
    func read<T: FixedWidthInteger>(from offset: Int = 0) -> T? {
        let size = MemoryLayout<T>.size
        guard offset + size <= count else { return nil }
        
        let value: T = withUnsafeBytes {
            $0.loadUnaligned(fromByteOffset: offset, as: T.self)
        }
        return value
    }
    
    func readBytes(from offset: Int, length: Int) -> Data? {
        guard offset >= 0, offset + length <= count else {
            return nil
        }
        return subdata(in: offset..<offset + length)
    }
    
    func readToEnd(from offset: Int) -> Data? {
        guard offset >= 0, offset < count else {
            return nil
        }
        return subdata(in: offset..<count)
    }
    
    func toJSON() -> Any? {
        try? JSONSerialization.jsonObject(with: self, options: .mutableContainers)
    }
    
    func toInt16Array() -> [Int16] {
        var result = [Int16]()
        self.withUnsafeBytes { rawBufferPointer in
            let int16Pointer = rawBufferPointer.bindMemory(to: Int16.self)
            guard let baseAddress = int16Pointer.baseAddress else { return }

            let count = self.count / MemoryLayout<Int16>.size
            let int16Buffer = UnsafeBufferPointer(start: baseAddress, count: count)
            result.append(contentsOf: int16Buffer)
        }
        return result
    }

}
